package org.jawa.database;

import java.io.File;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;

import javax.sql.DataSource;

import org.jawa.Constants;
import org.logicalcobwebs.proxool.ProxoolException;
import org.logicalcobwebs.proxool.ProxoolFacade;
import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;

/*
 * 提供Embedded DB的数据库连接池
 */
public class EmbeddedConnectionProvider implements ConnectionProvider {
	protected DataSource dataSource;

	private Properties settings;
	private String driver;
	private String serverURL;
	private String proxoolURL;
	private String username;
	private String password;
	private int minConnections = 3;
	private int maxConnections = 10;
	private int activeTimeout = 900000; // 15 minutes in milliseconds
	private double connectionTimeout = 0.5;


	public EmbeddedConnectionProvider() {
		loadProperties();
		dataSource = new JawaDataSource(this);
	}

	@Override
	public Connection getConnection() throws SQLException {
		Connection con;
		try {
			con = DriverManager.getConnection("proxool.jawashop");
		} catch (Exception e) {
			throw new SQLException(
					"EmbeddedConnectionProvider: Unable to find driver: " + e);
		}
		return con;

	}

	@Override
	public DataSource getDataSource() {
		return dataSource;
	}

	@Override
	public boolean isPooled() {
		return true;
	}

	@Override
	public void restart() {
		destroy();
		loadProperties();
		start();
	}

	@Override
	public void destroy() {
		settings = null;
		if (dataSource != null){
			try {
				(new SimpleJdbcTemplate(getDataSource())).update(
						"SHUTDOWN COMPACT", new Object[0]);
				ProxoolFacade.shutdown(0);
			} catch (Exception e) {
				e.printStackTrace();
			}
			dataSource = null;
		}
	}

	@Override
	public void start() {
		proxoolURL = "proxool.jawashop:" + getDriver() + ":" + getServerURL();
		settings = new Properties();
		settings.setProperty("proxool.maximum-activetime", Integer
				.toString(activeTimeout));
		settings.setProperty("proxool.maximum-connection-count", Integer
				.toString(getMaxConnections()));
		settings.setProperty("proxool.minimum-connection-count", Integer
				.toString(getMinConnections()));
		settings.setProperty("user", getUsername());
		settings.setProperty("password", (getPassword() != null ? getPassword()
				: ""));
		try {
			ProxoolFacade.registerConnectionPool(proxoolURL, settings);
		} catch (ProxoolException e) {
			// log.log(Level.SEVERE, "Error starting connection pool.", e);
			e.printStackTrace();
		}
	}

	/**
	 * 读取数据库默认的连接池配置
	 */
	private void loadProperties() {
		driver = "org.hsqldb.jdbcDriver";
		serverURL = (new StringBuilder()).append("jdbc:hsqldb:").append(
				Constants.getHomeDirectory()).append(File.separator).append(
				"database").append(File.separator).append("jawa").toString();
		username = "sa";
		password = "";
		minConnections = 3;
		maxConnections = 25;
		connectionTimeout = 0.5D;
	}

	public String getDriver() {
		return driver;
	}

	public void setDriver(String driver) {
		this.driver = driver;
	}

	public String getServerURL() {
		return serverURL;
	}

	public void setServerURL(String serverURL) {
		this.serverURL = serverURL;
	}

	public String getProxoolURL() {
		return proxoolURL;
	}

	public void setProxoolURL(String proxoolURL) {
		this.proxoolURL = proxoolURL;
	}

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public int getMinConnections() {
		return minConnections;
	}

	public void setMinConnections(int minConnections) {
		this.minConnections = minConnections;
	}

	public int getMaxConnections() {
		return maxConnections;
	}

	public void setMaxConnections(int maxConnections) {
		this.maxConnections = maxConnections;
	}

	public int getActiveTimeout() {
		return activeTimeout;
	}

	public void setActiveTimeout(int activeTimeout) {
		this.activeTimeout = activeTimeout;
	}

	public void setConnectionTimeout(double connectionTimeout) {
		this.connectionTimeout = connectionTimeout;
	}

	public double getConnectionTimeout() {
		return connectionTimeout;
	}

}
